package com.bonc.sign.configuration;

import com.bonc.sign.constants.Constants;
import com.bonc.sign.entity.SignConfDto;
import com.bonc.sign.exception.BusinessException;
import com.bonc.sign.mapper.SignConfMapper;
import com.bonc.sign.utils.QueryStringUtils;
import com.bonc.sign.utils.SM2Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

import static com.bonc.sign.constants.Constants.CHECK_SIGN_FLAG;


@Slf4j
public class SignInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (handler instanceof HandlerMethod) {
            ServletRequestAttributes requestAttributes =
                    (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (requestAttributes != null) {
                String queryString = requestAttributes.getRequest().getQueryString();
                if(queryString.indexOf(CHECK_SIGN_FLAG) > -1){
                    if(StringUtils.isBlank(queryString)){
                        throw new BusinessException("SIGN_ERROR", "url未拼接sign");
                    }
                    if (!verify(queryString)) {
                        throw new BusinessException("SIGN_ERROR", "签名验证不通过");
                    }
                }
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }


    private  boolean verify(String queryString) {
        Map<String, Object> parsedQueryString = QueryStringUtils.parse(queryString);
        if (parsedQueryString.size() == 0 || !parsedQueryString.containsKey(
                Constants.SIGN_KEY) || !parsedQueryString.containsKey(Constants.SYSTEM_KEY)) {
            throw new BusinessException("SIGN_ERROR", "未签名或签名错误");
        }
        String inputSign = (String) parsedQueryString.get(Constants.SIGN_KEY);
        String systemId = (String) parsedQueryString.get(Constants.SYSTEM_KEY);
        if (StringUtils.isAnyBlank(inputSign, systemId)) {
            throw new BusinessException("SIGN_ERROR", "未签名或签名入参错误");
        }
        String timestamp = (String) parsedQueryString.get(Constants.TIMESTAMP_KEY);
        if (StringUtils.isBlank(timestamp) || !NumberUtils.isParsable(timestamp)) {
            throw new BusinessException("TIMESTAMP_ERROR", "时间戳格式错误");
        } else {
            Long inputTimestamp = NumberUtils.createLong(timestamp);
            Long currentTimestamp = System.currentTimeMillis();
            //10分钟
            if (Math.abs(currentTimestamp - inputTimestamp) > 60 * 10 * 1000) {
                throw new BusinessException("TIMESTAMP_EXPIRED", "时间戳已过期");
            }
        }
        SignConfMapper signConfMapper = (SignConfMapper) SpringUtil.getBean(SignConfMapper.class);
        SignConfDto info = signConfMapper.getConfBySystemId(systemId);
		if (info == null || StringUtils.isAnyBlank(info.getEncryptAlgorithm(), info.getPrivateKey())) {
            log.info("SYSTEM_NOT_EXIST:{}", systemId,"系统配置不存在或未配置密钥");
			throw new BusinessException("SYSTEM_NOT_EXIST", "系统配置不存在或未配置密钥");
		}
        /*SignConfDto info = new SignConfDto();
        info.setPublicKey(pub1);*/
        try {
            //String s = QueryStringUtils.sortExcluded(parsedQueryString, Constants.SIGN_KEY);
            //签名
            //String resigned = SM2Utils.sign(info.getPrivateKey(), QueryStringUtils.sortExcluded(parsedQueryString, Constants.SIGN_KEY));

            return SM2Utils.verify(QueryStringUtils.sortExcluded(parsedQueryString, Constants.SIGN_KEY)
                    , info.getPublicKey(), inputSign);
            //验签
			/*if (StringUtils.equalsIgnoreCase(inputSign, resigned)) {
				return true;
			} else {
				throw new BusinessException("SIGN_ERROR", "签名错误");
			}*/
        } catch (Exception e) {
            throw new BusinessException("SIGN_ERROR", "无法验证签名");
        }

    }
    private static  String pub1 = "043C08C978C94157B46A071DA0BC33B46BADAC7F23DFE47858DB93C8892EC6BC17FA4D18083EAE745A0320CFBEF5FDB0B907FB1D6DDD315BAACD6DD6C5371A225D";
    private static String pri1 = "6B4A01D56B854C51FB5D90DF4D88EE75CF6F3FAF6C9C190D3F96DC27B925EBFB";
    private static String pub2 = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEHs1RZaN+f+48Gm3vfxSPbF1w0pEqzz6vz4r386QzhMHadMNRWHHnPf8qJs+AwiTUx7rd/o+Ymg2fvSG+ZXRHAQ==";
    private static String pri2 ="MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgOSrsEjJsdSLJrcCOU3ZLSigFO6tLSrM02H5NpyVdNxWgCgYIKoEcz1UBgi2hRANCAAQezVFlo35/7jwabe9/FI9sXXDSkSrPPq/PivfzpDOEwdp0w1FYcec9";
}
